<?php
namespace cosocket\system\server\websocket;

use Swoole\WebSocket\Server;
use Swoole\Process;
use Swoole\Runtime;
use cosocket\system\Logger;
use cosocket\system\server\abstracts\AbstractWebSocket;
use cosocket\system\server\interfaces\WebSocketInterface;

class AsyncWebSocket extends AbstractWebSocket implements WebSocketInterface
{
    public function run()
    {
        $this->initializeServer();
        $this->start();
    }

    public function initializeServer()
    {
        echo "异步模式启动 $this->host ,监听端口: " . $this->port . "\n";

        $this->ws = new Server($this->host, $this->port, SWOOLE_PROCESS);

        $this->ws->set($this->config);

        $this->ws->on('Start', [$this, 'onStart']);
        $this->ws->on('ManagerStart', [$this, 'onManagerStart']);
        $this->ws->on('ManagerStop', [$this, 'onManagerStop']);
        $this->ws->on('WorkerStart', [$this, 'onWorkerStart']);
        $this->ws->on('WorkerStop', [$this, 'onWorkerStop']);
        $this->ws->on('Open', [$this, 'onOpen']);
        $this->ws->on('Message', [$this, 'onMessage']);
        $this->ws->on('Close', [$this, 'onClose']);
        $this->ws->on('Task', [$this, 'onTask']);
        $this->ws->on('Finish', [$this, 'onFinish']);
        echo "\n初始化成功\n\n";
    }

    public function start()
    {
        echo "启动服务\n";
        $this->ws->start();
    }

    public function onStart($serv)
    {
        echo "Server started on port {$this->port}\n";
    }

    public function onManagerStart($serv)
    {
        echo "Manager started\n";
    }

    public function onManagerStop($serv)
    {
        echo "Manager stopped\n";
    }

    public function onWorkerStart($serv, $worker_id)
    {
        Runtime::enableCoroutine(SWOOLE_HOOK_ALL | SWOOLE_HOOK_CURL);
        echo "Worker started, worker_id: $worker_id\n";
    }

    public function onWorkerStop($serv, $worker_id)
    {
        echo "Worker stopped, worker_id: $worker_id\n";
    }

    //任务进程回调
    public function onTask($serv, $task)
    {
    }

    //任务结束后回调处理， 高版本可以自定会回调函数
    public function onFinish($serv, $task_id, $data)
    {
    }

    public function onOpen($ws, $request)
    {
        $this->handleRequest($request, $ws);
    }

    public function onMessage($ws, $frame)
    {
        $this->handleOpcode($frame, $ws, null);
    }

    public function onClose($ws, $fd)
    {
        Logger::info("Client {$fd} closed");
    }

    public function handleRequest($request, $ws)
    {
        try {
            if (!isset($request->header['upgrade']) || strtolower($request->header['upgrade']) != 'websocket') {
                return;
            }
        } catch (\Exception $e) {
            Logger::error("Catch An Exception File=[" . $e->getFile() . "|" . $e->getLine() . "] Code=[" . $e->getCode() . "], Message=[" . $e->getMessage() . "]");
        }
    }

    public function handleOpcode($frame, $ws, $request)
    {
        switch ($frame->opcode) {
            case 1: // Text frame
                if (!empty($frame->data)) {
                    $this->processFrame($frame, $ws, $request);
                }
                break;
            case 8: // Close frame
                $this->handleClose($frame, $ws, "Close frame");
                break;
        }
    }
}